package val.to;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import val.to.Utility.FlushedInputStream;
import val.to.config.Constants;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;

public class BitmapUtil {
	private static int MAX_IMAGE_DIMENSION = 720;

	public static Bitmap getBitmap(String url) {
		Bitmap bm = null;
		try {
			URL aURL = new URL(url);
			URLConnection conn = aURL.openConnection();
			conn.connect();
			InputStream is = conn.getInputStream();
			BufferedInputStream bis = new BufferedInputStream(is);
			bm = BitmapFactory.decodeStream(new FlushedInputStream(is));
			bis.close();
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
			bm = null;
		} finally {
		}
		return bm;
	}

	public static byte[] scaleImage(ContentResolver Resolver, Uri photoUri)
			throws FileNotFoundException {
		InputStream is = Resolver.openInputStream(photoUri);
		BitmapFactory.Options dbo = new BitmapFactory.Options();
		dbo.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(is, null, dbo);
		try {
			is.close();
		} catch (IOException e) {
		}

		int rotatedWidth = 0, rotatedHeight = 0;
		int orientation = 0;

		try {
			orientation = getOrientation(Resolver, photoUri);
		} catch (Exception ex) {
		}

		if (orientation == 90 || orientation == 270) {
			rotatedWidth = dbo.outHeight;
			rotatedHeight = dbo.outWidth;
		} else {
			rotatedWidth = dbo.outWidth;
			rotatedHeight = dbo.outHeight;
		}

		Bitmap srcBitmap;
		is = Resolver.openInputStream(photoUri);
		if (rotatedWidth > MAX_IMAGE_DIMENSION
				|| rotatedHeight > MAX_IMAGE_DIMENSION) {
			float widthRatio = ((float) rotatedWidth)
					/ ((float) MAX_IMAGE_DIMENSION);
			float heightRatio = ((float) rotatedHeight)
					/ ((float) MAX_IMAGE_DIMENSION);
			float maxRatio = Math.max(widthRatio, heightRatio);

			// Create the bitmap from file
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inSampleSize = (int) maxRatio;
			srcBitmap = BitmapFactory.decodeStream(is, null, options);
		} else {
			srcBitmap = BitmapFactory.decodeStream(is);
		}
		try {
			is.close();
		} catch (IOException e) {
		}

		/*
		 * if the orientation is not 0 (or -1, which means we don't know), we
		 * have to do a rotation.
		 */
		if (orientation > 0) {
			Matrix matrix = new Matrix();
			matrix.postRotate(orientation);

			srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
					srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
		}

		String type = Resolver.getType(photoUri);
		if (type == null) {
			String filenameArray[] = photoUri.getPath().split("\\.");
			type = filenameArray[filenameArray.length - 1];
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		if (type.equals("image/png") || type.equals("png")) {
			srcBitmap.compress(Bitmap.CompressFormat.PNG, Constants.PHOTO_UPLOAD_QUALITY, baos);
		} else if (type.equals("image/jpg") || type.equals("image/jpeg")
				|| type.equals("jpg") || type.equals("jpeg")) {
			srcBitmap.compress(Bitmap.CompressFormat.JPEG, Constants.PHOTO_UPLOAD_QUALITY, baos);
		}
		byte[] bMapArray = baos.toByteArray();
		
		try {
			baos.close();
		} catch (IOException e) {
		}
		srcBitmap.recycle();
		srcBitmap = null;
		return bMapArray;
	}

	public static int getOrientation(ContentResolver Resolver, Uri photoUri) {
		/* it's on the external media. */

		if (photoUri.getScheme().equals("file")) {
			ExifInterface exif = null;
			try {
				exif = new ExifInterface(photoUri.getPath());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			int res = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
					123123);
			if (res == ExifInterface.ORIENTATION_ROTATE_90) {
				return 90;
			} else if (res == ExifInterface.ORIENTATION_ROTATE_180) {
				return 180;
			} else if (res == ExifInterface.ORIENTATION_ROTATE_270) {
				return 270;
			}
			return 0;
		}

		else {
			Cursor cursor = Resolver
					.query(photoUri,
							new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
							null, null, null);

			if (cursor.getCount() != 1) {
				return -1;
			}

			cursor.moveToFirst();
			return cursor.getInt(0);
		}
	}

	// QuickLoad: takes more memory. shouldn't be used for large bitmaps that
	// might be cached
	public static Bitmap loadBitmap(Uri uri, Context context, int Width,
			int Height, boolean QuickLoad, boolean Rotate)
			throws FileNotFoundException {
		BitmapFactory.Options bounds = new BitmapFactory.Options();
		bounds.inJustDecodeBounds = true;
		BitmapFactory.decodeStream(context.getContentResolver()
				.openInputStream(uri), null, bounds);
		if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
			return null;

		BitmapFactory.Options opts = new BitmapFactory.Options();
		opts.inSampleSize = calculateInSampleSize(bounds, Width, Height,
				!QuickLoad);
		Bitmap bm = BitmapFactory.decodeStream(context.getContentResolver()
				.openInputStream(uri), null, opts);

		if (Rotate) {
			int orient = getOrientation(context.getContentResolver(), uri);
			if (orient != 0) {
				Matrix m = new Matrix();
				m.postRotate(orient);
				Bitmap newBM = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
						bm.getHeight(), m, true);
				bm.recycle();
				bm = newBM;
			}
		}
		return bm;
	}

	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight, boolean precise) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {
			if (width > height) {
				inSampleSize = Math.round((float) height / (float) reqHeight);
			} else {
				inSampleSize = Math.round((float) width / (float) reqWidth);
			}
		}

		// if bitmap's size doesn't have to be precise we change inSampleSize to
		// be the nearest power of 2. it suppose to be quicker that way but more
		// memory expansive
		if (!precise)
			inSampleSize = (int) Math
					.pow(2, Math.ceil(Math.sqrt(inSampleSize)));
		return inSampleSize;
	}
}
